﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Concurrent;
using YServer;
using GameProtocol.DTO.Fight;
using GameProtocol.DTO.Const;
using GameProtocol.DTO;
using GameProtocol;
using ServerApp.Cache;

namespace ServerApp.Logic.Fight
{
    public class FightRoom : AbsMutiplitySendHandler, IMessageReceive
    {
        RoleCache rcache;

        public int roomID;

         const int  buildCount=3;

        int create_num;

        /// <summary>
        /// 进入房间的连接，当个数等于 tokens 个数时广播初始化消息
        /// </summary>
        public List<YToken> enterTokens = new List<YToken>();

        /// <summary>
        /// 进入房间的连接，当个数等于 tokens 个数时广播初始化消息
        /// </summary>
        public List<YToken> inTokens = new List<YToken>();

        public List<YToken> tokens = new List<YToken>();

        public ConcurrentDictionary<string, int> roleModelDic = new ConcurrentDictionary<string, int>();

        public ConcurrentDictionary<int, AbsFightModel> modelMap = new ConcurrentDictionary<int, AbsFightModel>();

        public List<int> teamOne = new List<int>(), teamTwo = new List<int>();

        public MatchRoom mat_room;


        public void OnClientConn(YServer.YToken token)
        {
        }

        public void OnMessageReceive(YServer.YToken token, YServer.SocketModel model)
        {
            switch (model.command)
            {
                case FightProtocol.Enter_CREQ:
                    Enter(token);
                    break;
                case FightProtocol.Complete_CREQ:
                    Completed(token, model);
                    break;
                case FightProtocol.Move_CREQ:
                    Move(token, model);
                    break;
                case FightProtocol.Att_CREQ:
                    Att(token, model);
                    break;
                case FightProtocol.Demage_CREQ:
                    Demage(token, model);
                    break;
                default:
                    break;
            }
        }
        public void OnClientClose(YServer.YToken token, string error)
        {
            if (tokens.Contains(token)) {
                tokens.Remove(token);
            }

            if (tokens.Count == 0) {
                FunUtil.removeFightDe(this);
            }
        }

        void Init() {
         //   tokens = r.tokens;
            rcache = CacheFactory.roleCache;
            //初始化数据（英雄，炮塔，然后广播消息）

            //初始化英雄数据,并绑定角色名与单位id,单位id与模型的对应关系（暂时固定一个英雄）
            //正确来说是按照玩家选择的英雄id来初始化数据
            //规定 玩家的单位id从-100 开始
            create_num = -100;

            #region  玩家数据初始化
            
            //队伍一玩家数据
            foreach (string item in mat_room.teamOne)
            {
                HeroDataModel data = HeroData.heroDic[1];//获取英雄数据
                HeroFightModel model = new HeroFightModel();

                //初始化玩家数据
                model.id = create_num;
                model.modelCode = data.code;
                model.mtype = ModelType.Biology;
                model.name = data.name;
                model.hp = data.hpBase;
                model.maxhp = data.hpBase;
                model.att_num = data.attBase;
                model.att_range = data.att_range;
                model.att_speed = data.att_speed;
                model.mov_speed = data.mov_speed;
                model.attmode = data.attmode;

                model.role_name = item;
                model.coin = 200;
                model.level = 1;
                model.exp = 0;

                model.team = 1;

                create_num--;

                //添加角色名与单位id,单位id与模型的对应关系
                roleModelDic.TryAdd(item, model.id);
                modelMap.TryAdd(model.id, model);

                //添加进队伍一
                teamOne.Add(model.id);
            }

            //队伍二玩家数据
            foreach (string item in mat_room.teamTwo)
            {
                HeroDataModel data = HeroData.heroDic[1];//获取英雄数据
                HeroFightModel model = new HeroFightModel();

                //初始化玩家数据
                model.id = create_num;
                model.modelCode = data.code;
                model.mtype = ModelType.Biology;
                model.name = data.name;
                model.hp = data.hpBase;
                model.maxhp = data.hpBase;
                model.att_num = data.attBase;
                model.att_range = data.att_range;
                model.att_speed = data.att_speed;
                model.mov_speed = data.mov_speed;
                model.attmode = data.attmode;

                model.role_name = item;
                model.coin = 200;
                model.level = 1;
                model.exp = 0;

                model.team = 2;

                create_num--;

                //添加角色名与单位id,单位id与模型的对应关系
                roleModelDic.TryAdd(item, model.id);
                modelMap.TryAdd(model.id, model);

                //添加进队伍二
                teamTwo.Add(model.id);
            }

            #endregion


            #region 炮塔数据
            //初始化炮塔数据(规定 炮塔id从1开始到100)

            create_num = 1;

            //队伍一炮塔
            for (int i = 1; i < buildCount+1; i++)
            {
                BuildDataModel data = BuildData.buildDic[i];
                BuildFightModel model = new BuildFightModel();

                model.id = create_num;
                model.mtype = ModelType.Build;
                model.modelCode = data.code;
                model.name = data.name;
                model.hp = data.hp;
                model.maxhp = data.hp;
                model.att_num = data.att_num;
                model.att_range = data.att_range;
                model.att_speed = data.att_speed;
                model.mov_speed = 0;
                model.attmode = AttMode.Distant;
                model.born = data.born;
                model.bornTime = data.bornTime;
                model.canAtt = data.canAtt;

                model.team = 1;

                teamOne.Add(model.id);
                modelMap.TryAdd(model.id, model);

                create_num++;
            }

            //队伍二炮塔
            for (int j = 1; j < buildCount + 1; j++)
            {
                BuildDataModel data = BuildData.buildDic[j];
                BuildFightModel model = new BuildFightModel();

                model.id = create_num;
                model.mtype = ModelType.Build;
                model.modelCode = data.code;
                model.name = data.name;
                model.hp = data.hp;
                model.maxhp = data.hp;
                model.att_num = data.att_num;
                model.att_range = data.att_range;
                model.att_speed = data.att_speed;
                model.mov_speed = 0;
                model.attmode = AttMode.Distant;
                model.born = data.born;
                model.bornTime = data.bornTime;
                model.canAtt = data.canAtt;

                model.team = 2;

                modelMap.TryAdd(model.id, model);
                teamTwo.Add(model.id);

                create_num++;
            }
            #endregion


            //发送战斗场景初始化广播
            Broadcast(tokens,TypeProtocol.Fight,GetArea(), FightProtocol.Init_BRO,getDTOFromRoom());
            //Broadcast(tokens, TypeProtocol.Fight, GetArea(), FightProtocol.Init_BRO);
            //Console.WriteLine("init");
        }

        void Enter(YToken token) {
            if (enterTokens.Contains(token)) { return; }

            enterTokens.Add(token);

            //Console.WriteLine(enterTokens.Count+"   "+tokens.Count);

            if (enterTokens.Count == tokens.Count) {
                //发送战斗场景初始化广播
                Init();
            }
        }


        void Completed(YToken token,SocketModel model) {
            Console.WriteLine("com in");

            if (inTokens.Contains(token)) { return; }

            inTokens.Add(token);

            Console.WriteLine(inTokens.Count + "   " + tokens.Count);

            if (inTokens.Count == tokens.Count)
            {
                //发送战斗场景初始化完毕广播
                Console.WriteLine("com ok");
                Broadcast(tokens, TypeProtocol.Fight, roomID, FightProtocol.Complete_SRES);
            }
        }

        void Move(YToken token,SocketModel model) {
            
            Broadcast(tokens,TypeProtocol.Fight,GetArea(),FightProtocol.Move_BRO,model.GetTransModel<MoveDTO>());

        }

        void Att(YToken token, SocketModel model) {
            Broadcast(tokens, TypeProtocol.Fight, roomID, FightProtocol.Att_BRO, model.GetTransModel<AttDTO>());
        }


        void Demage(YToken token,SocketModel model) {
            DemageDTO dto=model.GetTransModel<DemageDTO>();
            
            AbsFightModel att=modelMap[dto.desID];
            AbsFightModel des=modelMap[dto.tarID];

            des.hp-=att.att_num;

            dto.model=des;

            Broadcast(tokens, TypeProtocol.Fight, roomID, FightProtocol.Demage_SRES, dto);
        }

        public void Clear() {
            mat_room = null;
            inTokens.Clear();
            enterTokens.Clear();
            roleModelDic.Clear();
            modelMap.Clear();
            teamOne.Clear();
            teamTwo.Clear();
            tokens.Clear();
        }

        public FightRoomDTO getDTOFromRoom() {
            FightRoomDTO dto = new FightRoomDTO();
            dto.roomID = this.roomID;
            List<AbsFightModel> one=new List<AbsFightModel>(),two=new List<AbsFightModel>();
            AbsFightModel model;
            foreach (int item in teamOne)
            {
                modelMap.TryGetValue(item, out model);
                one.Add(model);
            }

            foreach (int item in teamTwo)
            {
                modelMap.TryGetValue(item, out model);
                two.Add(model);
            }

            dto.teamOne = one.ToArray<AbsFightModel>();
            dto.teamTwo=two.ToArray<AbsFightModel>();

            return dto;
        }


        public override void SetProType()
        {
            type = TypeProtocol.Fight;
            area = roomID;
        }
    }
}
